package com.sudao.android.candle;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
import android.util.Log;

class CandleView extends SurfaceView implements SurfaceHolder.Callback {

    class CandleThread extends Thread {

        private int mCanvasHeight = 1;
        private int mCanvasWidth = 1;

        private long mLastTime;
        private int mMode;
		private Handler mHandler;

		private static final int OFFSET_X = 30;
		private static final int OFFSET_Y = 30;
		private static final String KEY_IS_LIGHTING = "isLighting";
		private static final String KEY_CURRENT_INDEX = "currentIndex";
		private static final String KEY_RUNNING = "mRun";

        private boolean mRun = false;

		private boolean mMulti = false;
		private String mShape;
		private int mCount;

	    private void loadAndApplyPreferences() {
            SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mContext);

            boolean multi = pref.getBoolean(Setting.MULTI, Setting.DEFAULT_MULTI);
            String shape = pref.getString(Setting.SHAPE, Setting.DEFAULT_SHAPE);
            int count = pref.getInt(Setting.COUNT, Setting.DEFAULT_COUNT);
 
            applySetting(multi, shape, count);
            Log.d("load and apply", " " + multi +" " + shape +" " + count);
	    }

		public void applySetting(boolean multi, String shape, int count) {
			mMulti = multi;
			mShape = shape;
			mCount = count;

			if (mMulti) {
				mCandleImage[0] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light5);
				mCandleImage[1] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light6);
				mCandleImage[2] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light7);
				mCandleImage[3] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light8); 
				mCandleBody = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_body);
			} else {
				mCandleImage[0] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light1);
				mCandleImage[1] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light2);
				mCandleImage[2] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light3);
				mCandleImage[3] = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light4);
				mCandleBody = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.body);
			}
		}

        private SurfaceHolder mSurfaceHolder;

        public CandleThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
            mSurfaceHolder = surfaceHolder;
            mHandler = handler;
            mContext = context;

			loadAndApplyPreferences();
        	Resources res = mContext.getResources();
			mCurrentImage = null;
			mCurrent = 0;
        	mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.background);
			mCurrentImage = mCandleImage[0];
			mCurrent = 0;

        }

		private static final int LIGHT_LEFT = 20;
		private static final int LIGHT_RIGHT = 300;

		private void drawSingleCandle(Canvas canvas) {
			mCandleBody.setBounds(LIGHT_LEFT + 80, OFFSET_Y + 75, 230, OFFSET_Y + 250 + 75);
            mCandleBody.draw(canvas);

			if (mCurrentImage == null)
				return;
            int width = mCurrentImage.getIntrinsicWidth();
            int height = mCurrentImage.getIntrinsicHeight();
			int left = (320 - width) / 2;
			int right = left + width / 2;
			mCurrentImage.setBounds(LIGHT_LEFT, OFFSET_Y, LIGHT_RIGHT, OFFSET_Y + height);
            mCurrentImage.draw(canvas);
			
			//drawCandle(160, 150, canvas);
			
		}
	
		private void drawMultiCandle(Canvas canvas) {
			if (mShape.equals(Setting.HEART)) {
				drawHeart(100, 160, 110f, canvas);
			} else if (mShape.equals(Setting.ILOVEU)) {
				drawI(30, 40, canvas);
				drawHeart(100, 160, 80f, canvas);
				drawU(380, 250, 50f, canvas);
			}
		}

		private void drawI(int left, int top, Canvas canvas) {
			int bodyHeight = mCandleBody.getIntrinsicHeight();
			int bodyWidth = mCandleBody.getIntrinsicWidth() / 2;
			int lightHeight = mCandleImage[0].getIntrinsicHeight();

			drawCandle(left, top, canvas);
			drawCandle(left, top + bodyHeight + lightHeight, canvas);
		}

		private void drawU(int offsetX, int offsetY, float a, Canvas canvas) {
			int thet;
			float x, y; 
			int delta = 360 / 45;
			
			int lightHeight = mCandleImage[0].getIntrinsicHeight();
			
			/*float x = (float) (a * Math.cos(Math.PI / 2));
			float y = (float) (a * Math.sin(Math.PI / 2));
			for (int i = 0; i < 5; i++) {
				drawCandle(offsetX - x, offsetY - y - i * lightHeight, canvas);
			}*/
			
			for (thet = 90; thet < 270; thet = thet + delta){
				float alpha = (float) (thet * Math.PI / 180);
				x = (float) (a * Math.cos(alpha));
				y = (float) (a * Math.sin(alpha));
				drawCandle(offsetY - y, offsetX - x, canvas);
			}
		}

		private void drawHeart(int offsetX, int offsetY, float a, Canvas canvas) {
			int thet;
			//float a =  110;
			//int offsetX = 100;
			//int offsetY = 160;
			int delta = 360 / mCount;	
			for(thet = 0; thet < 360; thet = thet + delta){
				float alpha = (float) (thet * Math.PI / 180);
				float r = (float) (a * (1 - Math.cos(alpha)));
				float x = (float) (r * Math.cos(alpha) * 1.3);
				float y = (float) (r * Math.sin(alpha));
				drawCandle(offsetY - y, offsetX - x, canvas);
			}
		}

		private void drawCandle(float x, float y, Canvas canvas) {
			int centerX = (int) x;
			int centerY = (int) y;
			int bodyHeight = mCandleBody.getIntrinsicHeight();
			int bodyWidth = mCandleBody.getIntrinsicWidth() / 2;
			mCandleBody.setBounds(centerX - bodyWidth, centerY, centerX + bodyWidth, centerY + bodyHeight);
            mCandleBody.draw(canvas);

			if (mCurrentImage == null)
				return;
			int lightHeight = mCurrentImage.getIntrinsicHeight();
			int lightWidth = mCurrentImage.getIntrinsicWidth() / 2;
			mCurrentImage.setBounds(centerX - lightWidth, centerY - lightHeight, centerX + lightWidth, centerY);
            mCurrentImage.draw(canvas);
		}

        public void doStart() {
            synchronized (mSurfaceHolder) {
            }
        }

        public void pause() {
            synchronized (mSurfaceHolder) {
            }
        }

        public Bundle saveState(Bundle map) {
            synchronized (mSurfaceHolder) {
                if (map != null) {
					map.putBoolean(KEY_IS_LIGHTING, mCurrentImage != null);
					map.putInt(KEY_CURRENT_INDEX, mCurrent);
					map.putBoolean(KEY_RUNNING, mRun);
                }
            }
            return map;
        }

        public synchronized void restoreState(Bundle savedState) {
            synchronized (mSurfaceHolder) {
				boolean isLighting = savedState.getBoolean(KEY_IS_LIGHTING);
				mCurrent = savedState.getInt(KEY_CURRENT_INDEX);
				setRunning(savedState.getBoolean(KEY_RUNNING));
				if (isLighting)
					mCurrentImage = mCandleImage[mCurrent];
            }
        }

        @Override
        public void run() {
            while (mRun) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        updatePhysics();
                        doDraw(c);
                    }
                } finally {
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

        public void setRunning(boolean b) {
            mRun = b;
        }

        public void setSurfaceSize(int width, int height) {
            synchronized (mSurfaceHolder) {
                mCanvasWidth = width;
                mCanvasHeight = height;
                mBackgroundImage = mBackgroundImage.createScaledBitmap(mBackgroundImage, width, height, true);
            }
        }

        public void unpause() {
            synchronized (mSurfaceHolder) {
            }
        }

        private void doDraw(Canvas canvas) {
            canvas.drawBitmap(mBackgroundImage, 0, 0, null);
			if (!mMulti) {
				drawSingleCandle(canvas);
			} else {
				drawMultiCandle(canvas);
			}
        }

        private void updatePhysics() {
            long now = System.currentTimeMillis();

            if (mLastTime > now) return;

            double elapsed = (now - mLastTime) / 1000.0;
			if (mCurrentImage != null)
				mCurrentImage = mCandleImage[mCurrent];
			++mCurrent;
			mCurrent = mCurrent % 4;
            mLastTime = now + 10;
        }
    }

    private Context mContext;
    private CandleThread thread;
	private Bitmap mBackgroundImage;
	private BitmapDrawable[] mCandleImage = new BitmapDrawable[4];
	private BitmapDrawable mCandleBody;
	private BitmapDrawable mCurrentImage;
	private int mCurrent;

    public CandleView(Context context, AttributeSet attrs) {
        super(context, attrs);

		mContext = context;
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        thread = new CandleThread(holder, mContext, new Handler() {
            @Override
            public void handleMessage(Message msg) {
            }
        });

        setFocusable(true);
    }

    public CandleThread getThread() {
        return thread;
    }

  //	@Override
  //  public void onWindowFocusChanged(boolean hasWindowFocus) {
  //      if (!hasWindowFocus) thread.pause();
  //  }

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			if (mCurrentImage == null)
				mCurrentImage = mCandleImage[mCurrent = 0];
			else
				mCurrentImage = null;
			return true;
		}
		return super.onTouchEvent(event);
	}

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        thread.setSurfaceSize(width, height);
    }

    public void surfaceCreated(SurfaceHolder holder) {
		if (thread != null) {
        	thread.setRunning(true);
        	thread.start();
			return;
		}

        thread = new CandleThread(holder, mContext, new Handler() {
            @Override
            public void handleMessage(Message msg) {
            }
        });
        thread.setRunning(true);
        thread.start();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
				thread = null;
            } catch (InterruptedException e) {
            }
        }
    }
}
